home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 51329 / 51329.xpi / chrome / firefound.jar / content / encryption.js next >
Text File  |  2009-12-14  |  11KB  |  295 lines

  1. var FIREFOUND_CRYPT = {
  2.     encrypt : function (msg, key) {
  3.         return btoa(this.cryptex.encrypt(msg, key, 128));
  4.     },
  5.     
  6.     decrypt : function (cipher, key) {
  7.         return this.cryptex.decrypt(atob(cipher), key, 128);
  8.     },
  9.     
  10.     cryptex : {
  11.         subBytes : function(s, Nb) {
  12.             for (var r=0; r<4; r++) {
  13.                 for (var c=0; c<Nb; c++) s[r][c] = this.Sbox[s[r][c]];
  14.             }
  15.             
  16.             return s;  
  17.         },
  18.         
  19.         shiftRows : function(s, Nb) {
  20.             var t = new Array(4);
  21.             for (var r=1; r<4; r++) {
  22.                 for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb];  // shift into temp copy
  23.                 for (var c=0; c<4; c++) s[r][c] = t[c];         // and copy back
  24.             }
  25.             
  26.             return s;
  27.         },
  28.         
  29.         mixColumns : function(s, Nb) {
  30.             for (var c=0; c<4; c++) {
  31.                 var a = new Array(4);  // 'a' is a copy of the current column from 's'
  32.                 var b = new Array(4);  // 'b' is aΓÇó{02} in GF(2^8)
  33.                 
  34.                 for (var i=0; i<4; i++) {
  35.                     a[i] = s[i][c];
  36.                     b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1;
  37.                 }
  38.                 
  39.                 s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3
  40.                 s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3
  41.                 s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3
  42.                 s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3
  43.             }
  44.             
  45.             return s;
  46.         },
  47.         
  48.         addRoundKey : function(state, w, rnd, Nb) {  // xor Round Key into state S [┬º5.1.4]
  49.             for (var r=0; r<4; r++) {
  50.                 for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r];
  51.             }
  52.             return state;
  53.         },
  54.         
  55.         subWord : function(w) {
  56.             for (var i=0; i<4; i++) w[i] = this.Sbox[w[i]];
  57.             return w;
  58.         },
  59.         
  60.         rotWord : function(w) {
  61.             w[4] = w[0];
  62.             for (var i=0; i<4; i++) w[i] = w[i+1];
  63.             return w;
  64.         },
  65.         
  66.         Sbox :  [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16],
  67.         Rcon : [ [0x00, 0x00, 0x00, 0x00],[0x01, 0x00, 0x00, 0x00],[0x02, 0x00, 0x00, 0x00],[0x04, 0x00, 0x00, 0x00],[0x08, 0x00, 0x00, 0x00],[0x10, 0x00, 0x00, 0x00],[0x20, 0x00, 0x00, 0x00],[0x40, 0x00, 0x00, 0x00],[0x80, 0x00, 0x00, 0x00],[0x1b, 0x00, 0x00, 0x00],[0x36, 0x00, 0x00, 0x00] ],
  68.         
  69.         escCtrlChars : function(str) {
  70.             return str.replace(/[\0\t\n\v\f\r\xa0!-]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });
  71.         },
  72.         
  73.         unescCtrlChars : function(str) {
  74.             return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });
  75.         },
  76.         
  77.         cipher : function(input, w) {
  78.             var Nb = 4;               // block size (in words): no of columns in state (fixed at 4 for AES)
  79.             var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
  80.  
  81.             var state = [[],[],[],[]];  // initialise 4xNb byte-array 'state' with input [┬º3.4]
  82.             for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i];
  83.  
  84.             state = this.addRoundKey(state, w, 0, Nb);
  85.  
  86.             for (var round=1; round<Nr; round++) {
  87.                 state = this.subBytes(state, Nb);
  88.                 state = this.shiftRows(state, Nb);
  89.                 state = this.mixColumns(state, Nb);
  90.                 state = this.addRoundKey(state, w, round, Nb);
  91.             }
  92.  
  93.             state = this.subBytes(state, Nb);
  94.             state = this.shiftRows(state, Nb);
  95.             state = this.addRoundKey(state, w, Nr, Nb);
  96.  
  97.             var output = new Array(4*Nb);  // convert state to 1-d array before returning [┬º3.4]
  98.             for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)];
  99.             return output;
  100.         },
  101.  
  102.         keyExpansion : function(key) {
  103.             var Nb = 4;            // block size (in words): no of columns in state (fixed at 4 for AES)
  104.             var Nk = key.length/4  // key length (in words): 4/6/8 for 128/192/256-bit keys
  105.             var Nr = Nk + 6;       // no of rounds: 10/12/14 for 128/192/256-bit keys
  106.  
  107.             var w = new Array(Nb*(Nr+1));
  108.             var temp = new Array(4);
  109.  
  110.             for (var i=0; i<Nk; i++) {
  111.             var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];
  112.                 w[i] = r;
  113.             }
  114.  
  115.             for (var i=Nk; i<(Nb*(Nr+1)); i++) {
  116.                 w[i] = new Array(4);
  117.                 for (var t=0; t<4; t++) temp[t] = w[i-1][t];
  118.                 if (i % Nk == 0) {
  119.                     temp = this.subWord(this.rotWord(temp));
  120.                     for (var t=0; t<4; t++) temp[t] ^= this.Rcon[i/Nk][t];
  121.                 } else if (Nk > 6 && i%Nk == 4) {
  122.                     temp = this.subWord(temp);
  123.                 }
  124.                 for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t];
  125.             }
  126.  
  127.             return w;
  128.         },
  129.  
  130.         encrypt : function(plaintext, password, nBits) {
  131.             if (!(nBits==128 || nBits==192 || nBits==256)) return '';  // standard allows 128/192/256 bit keys
  132.  
  133.             // for this example script, generate the key by applying cipher to 1st 16/24/32 chars of password; 
  134.             // for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1
  135.             var nBytes = nBits/8;  // no bytes in key
  136.             
  137.             /*
  138.             var pwBytes = new Array(nBytes);
  139.             for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
  140.             var key = this.cipher(pwBytes, this.keyExpansion(pwBytes));
  141.             key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
  142.             */
  143.             
  144.             // Key is a 16-count array of integers between 0 and 255
  145.             // We can achieve the same thing by sha1-hashing the password, getting the first 32 characters,
  146.             // and then converting each hex pair to decimal.
  147.             
  148.             var hash = FIREFOUND_CRYPT.hash(password, "SHA1", true);
  149.             var key = [];
  150.             
  151.             for (var i = 0; i < (nBytes * 2); i += 2) {
  152.                 var hexNum = hash.substr(i, 2);
  153.                 var decNum = parseInt(hexNum, 16);
  154.                 key.push(decNum);
  155.             }
  156.             
  157.             // initialise counter block (NIST SP800-38A ┬ºB.2): millisecond time-stamp for nonce in 1st 8 bytes,
  158.             // block counter in 2nd 8 bytes
  159.             var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
  160.             var counterBlock = new Array(blockSize);  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
  161.             var nonce = Math.round((new Date()).getTime() / 1000);  // seconds since 1-Jan-1970
  162.  
  163.             // encode nonce in two stages to cater for JavaScript 32-bit limit on bitwise ops
  164.             for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff;
  165.             for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff; 
  166.  
  167.             // generate key schedule - an expansion of the key into distinct Key Rounds for each round
  168.             var keySchedule = this.keyExpansion(key);
  169.  
  170.             var blockCount = Math.ceil(plaintext.length/blockSize);
  171.             var ciphertext = new Array(blockCount);  // ciphertext as array of strings
  172.  
  173.             for (var b=0; b<blockCount; b++) {
  174.                 // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
  175.                 // again done in two stages for 32-bit ops
  176.                 for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;
  177.                 for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8)
  178.  
  179.                 var cipherCntr = this.cipher(counterBlock, keySchedule);  // -- encrypt counter block --
  180.  
  181.                 // calculate length of final block:
  182.                 var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1;
  183.  
  184.                 var ct = '';
  185.                 
  186.                 for (var i=0; i<blockLength; i++) {  // -- xor plaintext with ciphered counter byte-by-byte --
  187.                     var plaintextByte = plaintext.charCodeAt(b*blockSize+i);
  188.                     var cipherByte = plaintextByte ^ cipherCntr[i];
  189.                     ct += String.fromCharCode(cipherByte);
  190.                 }
  191.                 // ct is now ciphertext for this block
  192.  
  193.                 ciphertext[b] = this.escCtrlChars(ct);  // escape troublesome characters in ciphertext
  194.             }
  195.  
  196.             // convert the nonce to a string to go on the front of the ciphertext
  197.             var ctrTxt = '';
  198.             for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]);
  199.             ctrTxt = this.escCtrlChars(ctrTxt);
  200.  
  201.             // use '-' to separate blocks, use Array.join to concatenate arrays of strings for efficiency
  202.             return ctrTxt + '-' + ciphertext.join('-');
  203.         },
  204.  
  205.         decrypt : function(ciphertext, password, nBits) {
  206.             if (!(nBits==128 || nBits==192 || nBits==256)) return '';  // standard allows 128/192/256 bit keys
  207.  
  208.             var nBytes = nBits/8;  // no bytes in key
  209.             
  210.             /*
  211.             var pwBytes = new Array(nBytes);
  212.             for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
  213.             var pwKeySchedule = this.keyExpansion(pwBytes);
  214.             var key = this.cipher(pwBytes, pwKeySchedule);
  215.             key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
  216.             */
  217.             
  218.             var hash = FIREFOUND_CRYPT.hash(password, "SHA1", true);
  219.             var key = [];
  220.  
  221.             for (var i = 0; i < (nBytes * 2); i += 2) {
  222.                 var hexNum = hash.substr(i, 2);
  223.                 var decNum = parseInt(hexNum, 16);
  224.                 key.push(decNum);
  225.             }
  226.  
  227.  
  228.             var keySchedule = this.keyExpansion(key);
  229.  
  230.             ciphertext = ciphertext.split('-');  // split ciphertext into array of block-length strings 
  231.  
  232.             var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
  233.             var counterBlock = new Array(blockSize);
  234.             var ctrTxt = this.unescCtrlChars(ciphertext[0]);
  235.             for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i);
  236.  
  237.             var plaintext = new Array(ciphertext.length-1);
  238.  
  239.             for (var b=1; b<ciphertext.length; b++) {
  240.                 for (var c=0; c<4; c++) counterBlock[15-c] = ((b-1) >>> c*8) & 0xff;
  241.                 for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff;
  242.  
  243.                 var cipherCntr = this.cipher(counterBlock, keySchedule);  // encrypt counter block
  244.  
  245.                 ciphertext[b] = this.unescCtrlChars(ciphertext[b]);
  246.  
  247.                 var pt = '';
  248.                 
  249.                 for (var i=0; i<ciphertext[b].length; i++) {
  250.                     var ciphertextByte = ciphertext[b].charCodeAt(i);
  251.                     var plaintextByte = ciphertextByte ^ cipherCntr[i];
  252.                     pt += String.fromCharCode(plaintextByte);
  253.                 }
  254.                 
  255.                 plaintext[b-1] = pt;  // b-1 'cos no initial nonce block in plaintext
  256.             }
  257.  
  258.             return plaintext.join('');
  259.         }
  260.     },
  261.     
  262.     hash : function(str, method, hex) {
  263.         var hash_engine;
  264.  
  265.         try {
  266.             hash_engine = Components.classes["@mozilla.org/security/hash;1"].createInstance(Components.interfaces["nsICryptoHash"]);
  267.             hash_engine.initWithString(method);
  268.  
  269.             var charcodes = new Array();
  270.  
  271.             for (var i = 0; i < str.length; i++)
  272.                 charcodes.push(str.charCodeAt(i));
  273.  
  274.             hash_engine.update(charcodes, str.length);
  275.  
  276.             if (hex) {            
  277.                 var hash = hash_engine.finish(false);
  278.  
  279.                 function toHexString(charCode) {
  280.                   return ("0" + charCode.toString(16)).slice(-2);
  281.                 }
  282.  
  283.                 // convert the binary hash data to a hex string.
  284.                 var s = [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
  285.                 return s;
  286.             }
  287.             else {
  288.                 return hash_engine.finish(true);
  289.             }
  290.         }
  291.         catch (e) {
  292.             return null;
  293.         }
  294.     }
  295. };